/******************************************************************************
Copyright (c) 2013-2014, Altera Corporation.  All rights reserved.

Redistribution and use of this software, in source and binary code forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of Altera Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT HOLDERS OR CONTRIBUTORS ARE ADVISED OF THE POSSIBILITY DAMAGE IS LIKELY TO OCCUR.
******************************************************************************/

#include "asm.h"

    AREA(TEST, CODE, READONLY, ALIGN=5)

	ALIGN32
	EXPORT(test_interrupts)
LABEL(test_interrupts)
	adr	pc, test_reset
	adr	pc, test_undef
	adr	pc, test_swi
	adr	pc, test_prefetch_abort

	adr	pc, test_data_abort
	adr	pc, test_unknown
	adr	pc, test_irq
	adr	pc, test_firq

LABEL(test_reset)
LABEL(test_unknown)
	b	test_reset	/*This should never he hit*/


/******************************
*	Undef Handler
******************************/


	EXPORT(undef_handler)
LABEL(undef_handler)
	DCD	0

LABEL(test_undef)		/* Return lr */
	add	lr,lr,#4 	/* Going to skip the instruction */
	stmfd	sp!, {r0-r3,lr}
	/*Make call*/
	ldr	r0, undef_handler
	cmp	r0,#0
	blxne	r0
	ldmfd	sp!, {r0-r3,pc}^

/********************************
*	SWI Handler
********************************/

	EXPORT(swi_handler)
LABEL(swi_handler)
	DCD	0

LABEL(test_swi)		/*Return lr */
	stmfd	sp!, {r0-r3,lr}
	/* Make call */
	ldr	r0, swi_handler
	cmp	r0,#0
	blxne	r0
	ldmfd	sp!, {r0-r3,pc}^


/********************************
* 	Prefetch Abort Handler
********************************/

	EXPORT(prefetch_abort_handler)
LABEL(prefetch_abort_handler)
	DCD	0

LABEL(test_prefetch_abort)	/*Return lr-4 */
	stmfd	sp!, {r0-r3,lr}
	/*Make call*/
	ldr	r0, prefetch_abort_handler
	cmp	r0,#0
	blxne	r0
	ldmfd	sp!, {r0-r3,pc}^


/********************************
* 	IRQ Handler
********************************/

	EXPORT(irq_handler)
LABEL(irq_handler)
	DCD	0

LABEL(test_irq)			/*Return lr-4 */
	sub	lr,lr,#4
	stmfd	sp!, {r0-r3,lr}
	/*Make call*/
	ldr	r0, irq_handler
	cmp	r0,#0
	blxne	r0
	ldmfd	sp!, {r0-r3,pc}^


/********************************
* 	Fast IRQ Handler
********************************/

	EXPORT(firq_handler)
LABEL(firq_handler)
	DCD	0

LABEL(test_firq)		/*Return lr-4 */
	sub	lr,lr,#4
	stmfd	sp!, {r0-r3,lr}
	/*Make call*/
	ldr	r0, firq_handler
	cmp	r0,#0
	blxne	r0
	ldmfd	sp!, {r0-r3,pc}^

/********************************
*	Data Abort Handler
********************************/

	EXPORT(data_abort_handler)
LABEL(data_abort_handler)
	DCD	0

LABEL(test_data_abort)		/*Return lr-8 */
	subs	lr,lr,#4
	stmfd	sp!, {r0-r3,lr}
	/*Make call*/
	ldr	r0, data_abort_handler
	cmp	r0,#0
	blxne	r0
	ldmfd	sp!, {r0-r3,pc}^

/********************************
*    Code for setting up stacks: 
********************************/

#define Disable_Ints	0xc0
#define Mode_Undef	0x1b
#define Mode_Irq	0x12
#define Mode_Firq	0x11
#define Mode_SWI	0x13
#define Mode_Abort	0x17

	EXPORT(set_undef_stack)
/*	r0 - stack for undef instruction */
LABEL(set_undef_stack)
	mov	r1, #(Disable_Ints _OR_ Mode_Undef)
	mrs	r2, CPSR /*Store off CPSR*/
	msr	CPSR_c, r1
	mov	sp, r0
	msr	CPSR_c, r2 /*Restore CPSR*/
	bx	lr

	EXPORT(set_abort_stack)
/*	r0 - stack for aborts  */
LABEL(set_abort_stack)
	mov	r1, #(Disable_Ints _OR_ Mode_Abort)
	mrs	r2, CPSR /*Store off CPSR*/
	msr	CPSR_c, r1
	mov	sp, r0
	msr	CPSR_c, r2 /*Restore CPSR*/
	bx	lr

	EXPORT(set_irq_stack)
LABEL(set_irq_stack)
	mov	r1, #(Disable_Ints _OR_ Mode_Irq)
	mrs	r2, CPSR /*Store off CPSR*/
	msr	CPSR_c, r1
	mov	sp, r0
	msr	CPSR_c, r2 /*Restore CPSR*/
	bx	lr

	EXPORT(set_firq_stack)
LABEL(set_firq_stack)
	mov	r1, #(Disable_Ints _OR_ Mode_Firq)
	mrs	r2, CPSR /*Store off CPSR*/
	msr	CPSR_c, r1
	mov	sp, r0
	msr	CPSR_c, r2 /*Restore CPSR*/
	bx	lr

	EXPORT(alt_mmu_disable2)
LABEL(alt_mmu_disable2)
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0,r0,#1
	mcr     p15, 0, r0, c1, c0, 0
	mov	r0,#0
	mov	pc,lr

	END
